<!doctype html>
<meta charset="utf8">

<emu-clause id="sec-temporal-timezone-objects">
  <h1>Temporal.TimeZone Objects</h1>
  <p>A Temporal.TimeZone object is an Object referencing a time zone.</p>

  <emu-clause id="sec-time-zone-names">
    <h1>Time Zone Names</h1>

    <emu-note type="editor">
      <p>
        The normative intention of this section is that an implementation must support UTC and a local time zone, which may also be UTC, or a named time zone like *"Europe/London"*, or an offset time zone like *"+01:00"*; and that the local time zone must in any case be consistent with the time zone offsets that can be determined using `Date.prototype.getTimezoneOffset()`, `Date.prototype.toString()`, and `Date.prototype.toTimeString()`.
        The exact formal definition of "local time zone" is still to be determined.
      </p>
    </emu-note>

    <p>
      An ECMAScript implementation must support a number of built-in time zones.
      At a minimum, implementations must support a built-in time zone named *"UTC"*.
      If the return value of DefaultTimeZone is different from *"UTC"*, and does not satisfy the syntax of a |TimeZoneNumericUTCOffset|, then implementations must support that time zone as a built-in time zone as well.
      In addition, implementations may support any number of other built-in time zones.
    </p>
    <p>
      Built-in time zones may be <dfn>named time zones</dfn>, represented by Strings for which IsValidTimeZoneName returns *true*.
      They may also be <dfn>offset time zones</dfn>, represented by Strings that conform to the syntax of |TimeZoneNumericUTCOffset|.
    </p>
    <p>
      <emu-xref href="#sec-temporal-timezone-constructor">The `Temporal.TimeZone` constructor</emu-xref>, when called with the name of a built-in time zone as the argument, will return a valid `Temporal.TimeZone` object.
      When called with any other string, it will throw a *RangeError* exception.
    </p>
    <p>
      Implementations are encouraged to support the Zone and Link names of the IANA Time Zone Database, and to use the best available current and historical information about their offsets from UTC and their daylight saving time rules in calculations.
    </p>
    <p>
      An ECMAScript implementation that includes the ECMA-402 Internationalization API has additional requirements for the built-in time zones that must be supported, as specified in the ECMA-402 specification.
    </p>

    <emu-clause id="sec-isvalidtimezonename" aoid="IsValidTimeZoneName">
      <h1>IsValidTimeZoneName ( _timeZone_ )</h1>

      <p>
        An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the IsValidTimeZoneName abstract operation as specified in the ECMA-402 specification.
        If an ECMAScript implementation does not include the ECMA-402 API the following specification of the IsValidTimeZoneName abstract operation is used.
      </p>
      <p>
        The abstract operation IsValidTimeZoneName takes argument _timeZone_, a String value. It returns *true* if _timeZone_, converted to upper case, is equal to one of the built-in named time zone names, converted to upper case.
        It returns *false* otherwise.
      </p>
      <p>
        Once IsValidTimeZoneName has returned *true* for a particular value of _timeZone_, for the lifetime of the surrounding agent, it may no longer return *false* for that value of _timeZone_, or for the value of CanonicalizeTimeZoneName(_timeZone_).
      </p>
      <p>The minimum implementation of IsValidTimeZoneName, supporting only the *"UTC"* time zone, performs the following steps when called:
      </p>

      <emu-alg>
        1. Assert: Type(_timeZone_) is String.
        1. Let _tzText_ be ! StringToCodePoints(_timeZone_).
        1. Let _tzUpperText_ be the result of toUppercase(_tzText_), according to the Unicode Default Case Conversion algorithm.
        1. Let _tzUpper_ be ! CodePointsToString(_tzUpperText_).
        1. If _tzUpper_ and *"UTC"* are the same sequence of code points, return *true*.
        1. Return *false*.
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-canonicalizetimezonename" aoid="CanonicalizeTimeZoneName">
      <h1>CanonicalizeTimeZoneName ( _timeZone_ )</h1>

      <p>
        An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the CanonicalizeTimeZoneName abstract operation as specified in the ECMA-402 specification.
        If an ECMAScript implementation does not include the ECMA-402 API the following specification of the CanonicalizeTimeZoneName abstract operation is used.
      </p>
      <p>
        The abstract operation CanonicalizeTimeZoneName takes argument _timeZone_, a String value, and returns the canonical and case-regularized form of _timeZone_.
      </p>
      <p>
        CanonicalizeTimeZoneName may only be called with a _timeZone_ parameter that is a valid time zone name according to IsValidTimeZoneName.
      </p>
      <p>
        The minimum implementation of CanonicalizeTimeZoneName, supporting only the *"UTC"* time zone, performs the following steps when called:
      </p>

      <emu-alg>
        1. Assert: Type(_timeZone_) is String.
        1. Assert: ! IsValidTimeZoneName(_timeZone_) is *true*.
        1. Return *"UTC"*.
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-defaulttimezone" aoid="DefaultTimeZone">
      <h1>DefaultTimeZone ( )</h1>

      <p>
        An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the DefaultTimeZone abstract operation as specified in the ECMA-402 specification.
        If an ECMAScript implementation does not include the ECMA-402 API the following specification of the DefaultTimeZone abstract operation is used.
      </p>
      <p>
        The DefaultTimeZone abstract operation returns a String value representing the host environment's current time zone, which is either a valid (<emu-xref href="#sec-isvalidtimezonename"></emu-xref>) and canonicalized (<emu-xref href="#sec-canonicalizetimezonename"></emu-xref>) time zone name, or an offset conforming to the syntax of a |TimeZoneNumericUTCOffset|.
      </p>
      <p>
        The minimum implementation of DefaultTimeZone, supporting only the *"UTC"* time zone, performs the following steps when called:
      </p>

      <emu-alg>
        1. Return *"UTC"*.
      </emu-alg>
    </emu-clause>
  </emu-clause>

  <emu-clause id="sec-temporal-timezone-constructor">
    <h1>The Temporal.TimeZone Constructor</h1>
    <p>The Temporal.TimeZone constructor:</p>
    <ul>
      <li>
        creates and initializes a new Temporal.TimeZone object when called as a constructor.
      </li>
      <li>
        is not intended to be called as a function and will throw an exception when called in that manner.
      </li>
      <li>
        may be used as the value of an `extends` clause of a class definition.
        Subclass constructors that intend to inherit the specified Temporal.TimeZone behaviour must
        include a super call to the %Temporal.TimeZone% constructor to create and initialize subclass
        instances with the necessary internal slots.
      </li>
    </ul>

    <emu-clause id="sec-temporal.timezone">
      <h1>Temporal.TimeZone ( _identifier_ )</h1>
      <p>
        When the `Temporal.TimeZone` function is called, the following steps are taken:
      </p>
      <emu-alg>
        1. If NewTarget is *undefined*, then
          1. Throw a *TypeError* exception.
        1. Set _identifier_ to ? ToString(_identifier_).
        1. If _identifier_ satisfies the syntax of a |TimeZoneNumericUTCOffset| (see <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref>), then
          1. Let _offsetNanoseconds_ be ? ParseTimeZoneOffsetString(_identifier_).
          1. Let _canonical_ be ! FormatTimeZoneOffsetString(_offsetNanoseconds_).
        1. Else,
          1. If ! IsValidTimeZoneName(_identifier_) is *false*, then
            1. Throw a *RangeError* exception.
          1. Let _canonical_ be ! CanonicalizeTimeZoneName(_identifier_).
        1. Return ? CreateTemporalTimeZone(_canonical_, NewTarget).
      </emu-alg>
    </emu-clause>
  </emu-clause>

  <emu-clause id="sec-properties-of-the-temporal-timezone-constructor">
    <h1>Properties of the Temporal.TimeZone Constructor</h1>
    <p>The value of the [[Prototype]] internal slot of the Temporal.TimeZone constructor is the intrinsic object %Function.prototype%.</p>
    <p>The Temporal.TimeZone constructor has the following properties:</p>

    <emu-clause id="sec-temporal-timezone-prototype">
      <h1>Temporal.TimeZone.prototype</h1>
      <p>The initial value of `Temporal.TimeZone.prototype` is %Temporal.TimeZone.prototype%.</p>
      <p>This property has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *false* }.</p>
    </emu-clause>

    <emu-clause id="sec-temporal.timezone.from">
      <h1>Temporal.TimeZone.from ( _item_ )</h1>
      <p>
        The `from` method takes one argument _item_.
        The following steps are taken:
      </p>
      <emu-alg>
        1. Return ? ToTemporalTimeZone(_item_).
      </emu-alg>
    </emu-clause>
  </emu-clause>

  <emu-clause id="sec-properties-of-the-temporal-timezone-prototype-object">
    <h1>Properties of the Temporal.TimeZone Prototype Object</h1>

    <p>The Temporal.TimeZone prototype object</p>
    <ul>
      <li>is itself an ordinary object.</li>
      <li>is not a Temporal.TimeZone instance and does not have a [[InitializedTemporalTimeZone]] internal slot.</li>
      <li>has a [[Prototype]] internal slot whose value is %Object.prototype%.</li>
    </ul>

    <emu-clause id="sec-temporal.timezone.prototype.constructor">
      <h1>Temporal.TimeZone.prototype.constructor</h1>
      <p>The initial value of `Temporal.TimeZone.prototype.constructor` is %Temporal.TimeZone%.</p>
    </emu-clause>

    <emu-clause id="sec-temporal.timezone.prototype-@@tostringtag">
      <h1>Temporal.TimeZone.prototype[ @@toStringTag ]</h1>
      <p>
        The initial value of the @@toStringTag property is the string value *"Temporal.TimeZone"*.
      </p>
      <p>
        This property has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *true* }.
      </p>
    </emu-clause>

    <emu-clause id="sec-get-temporal.timezone.prototype.id">
      <h1>get Temporal.TimeZone.prototype.id</h1>
      <p>
        `Temporal.TimeZone.prototype.id` is an accessor property whose set accessor function is *undefined*.
        Its get accessor function performs the following steps:
      </p>
      <emu-alg>
        1. Let _timeZone_ be the *this* value.
        1. Return ? ToString(_timeZone_).
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal.timezone.prototype.getoffsetnanosecondsfor">
      <h1>Temporal.TimeZone.prototype.getOffsetNanosecondsFor ( _instant_ )</h1>
      <p>
        The `getOffsetNanosecondsFor` method takes one argument _instant_.
        The following steps are taken:
      </p>
      <emu-alg>
        1. Let _timeZone_ be the *this* value.
        1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
        1. Set _instant_ to ? ToTemporalInstant(_instant_).
        1. If _timeZone_.[[OffsetNanoseconds]] is not *undefined*, return _timeZone_.[[OffsetNanoseconds]].
        1. Return ! GetIANATimeZoneOffsetNanoseconds(_instant_.[[Nanoseconds]], _timeZone_.[[Identifier]]).
      </emu-alg>
      <p>
        This function is the <dfn>%Temporal.TimeZone.prototype.getOffsetNanosecondsFor%</dfn> intrinsic object.
      </p>
    </emu-clause>

    <emu-clause id="sec-temporal.timezone.prototype.getoffsetstringfor">
      <h1>Temporal.TimeZone.prototype.getOffsetStringFor ( _instant_ )</h1>
      <p>
        The `getOffsetStringFor` method takes one argument _instant_.
        The following steps are taken:
      </p>
      <emu-alg>
        1. Let _timeZone_ be the *this* value.
        1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
        1. Set _instant_ to ? ToTemporalInstant(_instant_).
        1. Return ? BuiltinTimeZoneGetOffsetStringFor(_timeZone_, _instant_).
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal.timezone.prototype.getplaindatetimefor">
      <h1>Temporal.TimeZone.prototype.getPlainDateTimeFor ( _instant_ [ , _calendarLike_ ] )</h1>
      <p>
        The `getPlainDateTimeFor` method takes two arguments, _instant_ and _calendarLike_.
        The following steps are taken:
      </p>
      <emu-alg>
        1. Let _timeZone_ be the *this* value.
        1. Set _instant_ to ? ToTemporalInstant(_instant_).
        1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_calendarLike_).
        1. Return ? BuiltinTimeZoneGetPlainDateTimeFor(_timeZone_, _instant_, _calendar_).
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal.timezone.prototype.getinstantfor">
      <h1>Temporal.TimeZone.prototype.getInstantFor ( _dateTime_ [ , _options_ ] )</h1>
      <p>
        The `getInstantFor` method takes two arguments, _dateTime_ and _options_.
        The following steps are taken:
      </p>
      <emu-alg>
        1. Let _timeZone_ be the *this* value.
        1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
        1. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_).
        1. Set _options_ to ? GetOptionsObject(_options_).
        1. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
        1. Return ? BuiltinTimeZoneGetInstantFor(_timeZone_, _dateTime_, _disambiguation_).
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal.timezone.prototype.getpossibleinstantsfor">
      <h1>Temporal.TimeZone.prototype.getPossibleInstantsFor ( _dateTime_ )</h1>
      <p>
        The `getPossibleInstantsFor` method takes one argument _dateTime_.
        The following steps are taken:
      </p>
      <emu-alg>
        1. Let _timeZone_ be the *this* value.
        1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimezone]]).
        1. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_).
        1. If _timeZone_.[[OffsetNanoseconds]] is not *undefined*, then
          1. Let _epochNanoseconds_ be ! GetEpochFromISOParts(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]]).
          1. Let _instant_ be ! CreateTemporalInstant(_epochNanoseconds_ − _timeZone_.[[OffsetNanoseconds]]).
          1. Return ! CreateArrayFromList(« _instant_ »).
        1. Let _possibleEpochNanoseconds_ be ? GetIANATimeZoneEpochValue(_timeZone_.[[Identifier]], _dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]]).
        1. Let _possibleInstants_ be a new empty List.
        1. For each value _epochNanoseconds_ in _possibleEpochNanoseconds_, do
          1. Let _instant_ be ! CreateTemporalInstant(_epochNanoseconds_).
          1. Append _instant_ to _possibleInstants_.
        1. Return ! CreateArrayFromList(_possibleInstants_).
      </emu-alg>
      <p>
        This function is the <dfn>%Temporal.TimeZone.prototype.getPossibleInstantsFor%</dfn> intrinsic object.
      </p>
    </emu-clause>

    <emu-clause id="sec-temporal.timezone.prototype.getnexttransition">
      <h1>Temporal.TimeZone.prototype.getNextTransition ( _startingPoint_ )</h1>
      <p>
        The `getNextTransition` method takes one argument _startingPoint_.
        The following steps are taken:
      </p>
      <emu-alg>
        1. Let _timeZone_ be the *this* value.
        1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
        1. Set _startingPoint_ to ? ToTemporalInstant(_startingPoint_).
        1. If _timeZone_.[[OffsetNanoseconds]] is not *undefined*, return *null*.
        1. Let _transition_ be ? GetIANATimeZoneNextTransition(_startingPoint_.[[Nanoseconds]], _timeZone_.[[Identifier]]).
        1. If _transition_ is *null*, return *null*.
        1. Return ! CreateTemporalInstant(_transition_).
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal.timezone.prototype.getprevioustransition">
      <h1>Temporal.TimeZone.prototype.getPreviousTransition ( _startingPoint_ )</h1>
      <p>
        The `getPreviousTransition` method takes one argument _startingPoint_.
        The following steps are taken:
      </p>
      <emu-alg>
        1. Let _timeZone_ be the *this* value.
        1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
        1. Set _startingPoint_ to ? ToTemporalInstant(_startingPoint_).
        1. If _timeZone_.[[OffsetNanoseconds]] is not *undefined*, return *null*.
        1. Let _transition_ be ? GetIANATimeZonePreviousTransition(_startingPoint_.[[Nanoseconds]], _timeZone_.[[Identifier]]).
        1. If _transition_ is *null*, return *null*.
        1. Return ! CreateTemporalInstant(_transition_).
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal.timezone.prototype.tostring">
      <h1>Temporal.TimeZone.prototype.toString ( )</h1>
      <p>
        The following steps are taken:
      </p>
      <emu-alg>
        1. Let _timeZone_ be the *this* value.
        1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
        1. Return _timeZone_.[[Identifier]].
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal.timezone.prototype.tojson">
      <h1>Temporal.TimeZone.prototype.toJSON ( )</h1>
      <p>
        The following steps are taken:
      </p>
      <emu-alg>
        1. Let _timeZone_ be the *this* value.
        1. Return ? ToString(_timeZone_).
      </emu-alg>
    </emu-clause>
  </emu-clause>

  <emu-clause id="sec-properties-of-temporal-timezone-instances">
    <h1>Properties of Temporal.TimeZone Instances</h1>

    <p>
      Temporal.TimeZone instances are ordinary objects that inherit properties from the %Temporal.TimeZone.prototype% intrinsic object.
      Temporal.TimeZone instances are initially created with the internal slots described in <emu-xref href="#table-internal-slots-of-temporaltimezone-instances"></emu-xref>.
    </p>
    <emu-table id="table-internal-slots-of-temporaltimezone-instances" caption="Internal Slots of Temporal.TimeZone Instances">
      <table>
        <tbody>
          <tr>
            <th>
              Internal Slot
            </th>
            <th>
              Description
            </th>
          </tr>
          <tr>
            <td>
              [[InitializedTemporalTimeZone]]
            </td>
            <td>
              The only specified use of this slot is for distinguishing Temporal.TimeZone instances from other objects.
            </td>
          </tr>
          <tr>
            <td>
              [[Identifier]]
            </td>
            <td>
              A String value.
            </td>
          </tr>
          <tr>
            <td>
              [[OffsetNanoseconds]]
            </td>
            <td>
              A Number value for nanoseconds representing the constant offset of this time zone to UTC, or *undefined* if the time zone is an IANA time zone.
            </td>
          </tr>
        </tbody>
      </table>
    </emu-table>
  </emu-clause>

  <emu-clause id="sec-temporal-timezone-abstract-ops">
    <h1>Abstract operations</h1>

    <emu-clause id="sec-temporal-parsetemporaltimezone" aoid="ParseTemporalTimeZone">
      <h1>ParseTemporalTimeZone ( _string_ )</h1>
      <emu-alg>
        1. Assert: Type(_string_) is String.
        1. Let _result_ be ? ParseTemporalTimeZoneString(_string_).
        1. If _result_.[[Z]] is not *undefined*, return *"UTC"*.
        1. Return _result_.[[Name]].
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal-createtemporaltimezone" aoid="CreateTemporalTimeZone">
      <h1>CreateTemporalTimeZone ( _identifier_ [ , _newTarget_ ] )</h1>
      <emu-alg>
        1. If _newTarget_ is not present, set it to %Temporal.TimeZone%.
        1. Let _object_ be ? OrdinaryCreateFromConstructor(_newTarget_, *"%Temporal.TimeZone.prototype%"*, « [[InitializedTemporalTimeZone]], [[Identifier]], [[OffsetNanoseconds]] »).
        1. Set _object_.[[Identifier]] to _identifier_.
        1. If _identifier_ satisfies the syntax of a |TimeZoneNumericUTCOffset| (see <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref>), then
          1. Set _object_.[[OffsetNanoseconds]] to ! ParseTimeZoneOffsetString(_identifier_).
        1. Else,
          1. Assert: ! CanonicalizeTimeZoneName(_identifier_) is _identifier_.
          1. Set _object_.[[OffsetNanoseconds]] to *undefined*.
        1. Return _object_.
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal-getisopartsfromepoch" aoid="GetISOPartsFromEpoch">
      <h1>GetISOPartsFromEpoch ( _epochNanoseconds_ )</h1>
      <p>
        The abstract operation GetISOPartsFromEpoch returns the components of a date corresponding to the given number of nanoseconds since the Unix epoch in UTC.
      </p>
      <emu-alg>
        1. Let _remainderNs_ be _epochNanoseconds_ modulo 10<sup>6</sup>.
        1. Let _epochMilliseconds_ be (_epochNanoseconds_ − _remainderNs_) / 10<sup>6</sup>.
        1. Let _year_ be ! YearFromTime(_epochMilliseconds_).
        1. Let _month_ be ! MonthFromTime(_epochMilliseconds_) + 1.
        1. Let _day_ be ! DateFromTime(_epochMilliseconds_).
        1. Let _hour_ be ! HourFromTime(_epochMilliseconds_).
        1. Let _minute_ be ! MinFromTime(_epochMilliseconds_).
        1. Let _second_ be ! SecFromTime(_epochMilliseconds_).
        1. Let _millisecond_ be ! msFromTime(_epochMilliseconds_).
        1. Let _microsecond_ be floor(_remainderNs_ / 1000) modulo 1000.
        1. Let _nanosecond_ be _remainderNs_ modulo 1000.
        1. Return the new Record {
          [[Year]]: _year_,
          [[Month]]: _month_,
          [[Day]]: _day_,
          [[Hour]]: _hour_,
          [[Minute]]: _minute_,
          [[Second]]: _second_,
          [[Millisecond]]: _millisecond_,
          [[Microsecond]]: _microsecond_,
          [[Nanosecond]]: _nanosecond_
          }.
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal-getianatimezoneepochvalue" aoid="GetIANATimeZoneEpochValue">
      <h1>GetIANATimeZoneEpochValue ( _timeZoneIdentifier_, _year_, _month_, _day_, _hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_ )</h1>
      <p>
        The abstract operation GetIANATimeZoneEpochValue is an implementation-defined algorithm that returns a List of integers.
        Each integer in the List represents a number of nanoseconds since the Unix epoch in UTC that may correspond to the given calendar date and wall-clock time in the IANA time zone identified by _timeZoneIdentifier_.
      </p>
      <p>
        When the input represents a local time repeating multiple times at a negative time zone transition (e.g. when the daylight saving time ends or the time zone offset is decreased due to a time zone rule change), the returned List will have more than one element.
        When the input represents a skipped local time at a positive time zone transition (e.g. when the daylight saving time starts or the time zone offset is increased due to a time zone rule change), the returned List will be empty.
        Otherwise, the returned List will have one element.
      </p>
    </emu-clause>

    <emu-clause id="sec-temporal-getianatimezoneoffsetnanoseconds" aoid="GetIANATimeZoneOffsetNanoseconds">
      <h1>GetIANATimeZoneOffsetNanoseconds ( _epochNanoseconds_, _timeZoneIdentifier_ )</h1>
      <p>
        The abstract operation GetIANATimeZoneOffsetNanoseconds is an implementation-defined algorithm that returns an integer representing the offset of the IANA time zone identified by _timeZoneIdentifier_ from UTC, at the instant corresponding to _epochNanoseconds_.
      </p>
      <p>
        Given the same values of _epochNanoseconds_ and _timeZoneIdentifier_, the result must be the same for the lifetime of the surrounding agent.
      </p>
    </emu-clause>

    <emu-clause id="sec-temporal-getianatimezonenexttransition" aoid="GetIANATimeZoneNextTransition">
      <h1>GetIANATimeZoneNextTransition ( _epochNanoseconds_, _timeZoneIdentifier_ )</h1>
      <p>
        The abstract operation GetIANATimeZoneNextTransition is an implementation-defined algorithm that returns an integer representing the number of nanoseconds since the Unix epoch in UTC that corresponds to the first time zone transition after _epochNanoseconds_ in the IANA time zone identified by _timeZoneIdentifier_.
      </p>
    </emu-clause>

    <emu-clause id="sec-temporal-getianatimezoneprevioustransition" aoid="GetIANATimeZonePreviousTransition">
      <h1>GetIANATimeZonePreviousTransition ( _epochNanoseconds_, _timeZoneIdentifier_ )</h1>
      <p>
        The abstract operation GetIANATimeZonePreviousTransition is an implementation-defined algorithm that returns an integer representing the number of nanoseconds since the Unix epoch in UTC that corresponds to the last time zone transition before _epochNanoseconds_ in the IANA time zone identified by _timeZoneIdentifier_.
      </p>
    </emu-clause>

    <emu-clause id="sec-temporal-parsetimezoneoffsetstring" aoid="ParseTimeZoneOffsetString">
      <h1>ParseTimeZoneOffsetString ( _offsetString_ )</h1>
      <p>
        The abstract operation ParseTimeZoneOffsetString returns a number of offset nanoseconds that corresponds to the given time zone offset string.
      </p>
      <emu-alg>
        1. Assert: Type(_offsetString_) is String.
        1. If _offsetString_ does not satisfy the syntax of a |TimeZoneNumericUTCOffset| (see <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref>), then
          1. Throw a *RangeError* exception.
        1. Let _sign_, _hours_, _minutes_, _seconds_, and _fraction_ be the parts of _offsetString_ produced respectively by the |TimeZoneUTCOffsetSign|, |TimeZoneUTCOffsetHour|, |TimeZoneUTCOffsetMinute|, |TimeZoneUTCOffsetSecond|, and |TimeZoneUTCOffsetFraction| productions, or *undefined* if not present.
        1. If either _hours_ or _sign_ are *undefined*, throw a *RangeError* exception.
        1. If _sign_ is the code unit 0x002D (HYPHEN-MINUS) or 0x2212 (MINUS SIGN), then
          1. Set _sign_ to −1.
        1. Else,
          1. Set _sign_ to 1.
        1. Set _hours_ to ! ToIntegerOrInfinity(_hours_).
        1. Set _minutes_ to ! ToIntegerOrInfinity(_minutes_).
        1. Set _seconds_ to ! ToIntegerOrInfinity(_seconds_).
        1. If _fraction_ is not *undefined*, then
          1. Set _fraction_ to the string-concatenation of the previous value of _fraction_ and the string *"000000000"*.
          1. Let _nanoseconds_ be the String value equal to the substring of _fraction_ consisting of the code units with indices 0 (inclusive) through 9 (exclusive).
          1. Set _nanoseconds_ to ! ToIntegerOrInfinity(_nanoseconds_).
        1. Else,
          1. Let _nanoseconds_ be 0.
        1. Return _sign_ × (((_hours_ × 60 + _minutes_) × 60 + _seconds_) × 10<sup>9</sup> + _nanoseconds_).
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal-formattimezoneoffsetstring" aoid="FormatTimeZoneOffsetString">
      <h1>FormatTimeZoneOffsetString ( _offsetNanoseconds_ )</h1>
      <emu-alg>
        1. Assert: _offsetNanoseconds_ is an integer.
        1. If _offsetNanoseconds_ ≥ 0, let _sign_ be *"+"*; otherwise, let _sign_ be *"-"*.
        1. Let _nanoseconds_ be abs(_offsetNanoseconds_) modulo 10<sup>9</sup>.
        1. Let _seconds_ be floor(_offsetNanoseconds_ / 10<sup>9</sup>) modulo 60.
        1. Let _minutes_ be floor(_offsetNanoseconds_ / (6 × 10<sup>10</sup>)) modulo 60.
        1. Let _hours_ be floor(_offsetNanoseconds_ / (3.6 × 10<sup>12</sup>)).
        1. Let _h_ be _hours_, formatted as a two-digit decimal number, padded to the left with a zero if necessary.
        1. Let _m_ be _minutes_, formatted as a two-digit decimal number, padded to the left with a zero if necessary.
        1. Let _s_ be _seconds_, formatted as a two-digit decimal number, padded to the left with a zero if necessary.
        1. If _nanoseconds_ ≠ 0, then
          1. Let _fraction_ be _nanoseconds_, formatted as a nine-digit decimal number, padded to the left with zeroes if necessary.
          1. Set _fraction_ to the longest possible substring of _fraction_ starting at position 0 and not ending with the code unit 0x0030 (DIGIT ZERO).
          1. Let _post_ be the string-concatenation of the code unit 0x003A (COLON), _s_, the code unit 0x002E (FULL STOP), and _fraction_.
        1. Else if seconds ≠ 0, then
          1. Let _post_ be the string-concatenation of the code unit 0x003A (COLON) and _s_.
        1. Return the string-concatenation of _sign_, _h_, the code unit 0x003A (COLON), _m_, and _post_.
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal-totemporaltimezone" aoid="ToTemporalTimeZone">
      <h1>ToTemporalTimeZone ( _temporalTimeZoneLike_ )</h1>
      <emu-alg>
        1. If Type(_temporalTimeZoneLike_) is Object, then
          1. If _temporalTimeZoneLike_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
            1. Return _temporalTimeZoneLike_.[[TimeZone]].
          1. If ? HasProperty(_temporalTimeZoneLike_, *"timeZone"*) is *false*, return _temporalTimeZoneLike_.
          1. Set _temporalTimeZoneLike_ to ? Get(_temporalTimeZoneLike_, *"timeZone"*).
          1. If Type(_temporalTimeZoneLike_) is Object and ? HasProperty(_temporalTimeZoneLike_, *"timeZone"*) is *false*, return _temporalTimeZoneLike_.
        1. Let _identifier_ be ? ToString(_temporalTimeZoneLike_).
        1. Let _result_ be ? ParseTemporalTimeZone(_identifier_).
        1. Return ? CreateTemporalTimeZone(_result_).
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal-getoffsetnanosecondsfor" aoid="GetOffsetNanosecondsFor">
      <h1>GetOffsetNanosecondsFor ( _timeZone_, _instant_ )</h1>
      <emu-alg>
        1. Let _getOffsetNanosecondsFor_ be ? GetMethod(_timeZone_, *"getOffsetNanosecondsFor"*).
        1. If _getOffsetNanosecondsFor_ is *undefined*, set _getOffsetNanosecondsFor_ to %Temporal.TimeZone.prototype.getOffsetNanosecondsFor%.
        1. Let _offsetNanoseconds_ be ? Call(_getOffsetNanosecondsFor_, _timeZone_, « _instant_ »).
        1. If Type(_offsetNanoseconds_) is not Number, throw a *TypeError* exception.
        1. If ! IsIntegralNumber(_offsetNanoseconds_) is *false*, throw a *RangeError* exception.
        1. Set _offsetNanoseconds_ to ℝ(_offsetNanoseconds_).
        1. If abs(_offsetNanoseconds_) &gt; 86400 × 10<sup>9</sup>, throw a *RangeError* exception.
        1. Return _offsetNanoseconds_.
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal-builtintimezonegetoffsetstringfor" aoid="BuiltinTimeZoneGetOffsetStringFor">
      <h1>BuiltinTimeZoneGetOffsetStringFor ( _timeZone_, _instant_ )</h1>
      <emu-alg>
        1. Let _offsetNanoseconds_ be ? GetOffsetNanosecondsFor(_timeZone_, _instant_).
        1. Return ! FormatTimeZoneOffsetString(_offsetNanoseconds_).
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal-builtintimezonegetplaindatetimefor" aoid="BuiltinTimeZoneGetPlainDateTimeFor">
      <h1>BuiltinTimeZoneGetPlainDateTimeFor ( _timeZone_, _instant_, _calendar_ )</h1>
      <p>
        The abstract operation BuiltinTimeZoneGetPlainDateTimeFor is the internal implementation of the `Temporal.TimeZone.prototype.getPlainDateTimeFor` method.
        It observably calls the given _timeZone_'s `getOffsetNanosecondsFor` method.
      </p>
      <emu-alg>
        1. Let _offsetNanoseconds_ be ? GetOffsetNanosecondsFor(_timeZone_, _instant_).
        1. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]).
        1. Set _result_ to ! BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_).
        1. Return ? CreateTemporalDateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]], _calendar_).
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal-builtintimezonegetinstantfor" aoid="BuiltinTimeZoneGetInstantFor">
      <h1>BuiltinTimeZoneGetInstantFor ( _timeZone_, _dateTime_, _disambiguation_ )</h1>
      <p>
        The abstract operation BuiltinTimeZoneGetInstantFor is the internal implementation of the `Temporal.TimeZone.prototype.getInstantFor` method.
        It observably calls the given _timeZone_'s `getPossibleInstantsFor` method at least once.
        If that call returns an empty array and _disambiguation_ is not *"reject"*, it observably calls the time zone's `getOffsetNanosecondsFor` method twice, and `getPossibleInstantsFor` an additional time.
      </p>
      <emu-alg>
        1. Assert: _dateTime_ has an [[InitializedTemporalDateTime]] internal slot.
        1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_).
        1. Let _n_ be _possibleInstants_'s length.
        1. If _n_ = 1, then
          1. Return _possibleInstants_[0].
        1. If _n_ ≠ 0, then
          1. If _disambiguation_ is *"earlier"* or *"compatible"*, then
            1. Return _possibleInstants_[0].
          1. If _disambiguation_ is *"later"*, then
            1. Return _possibleInstants_[_n_ − 1].
          1. Assert: _disambiguation_ is *"reject"*.
          1. Throw a *RangeError* exception.
        1. Assert: _n_ = 0.
        1. If _disambiguation_ is *"reject"*, then
          1. Throw a *RangeError* exception.
        1. Let _epochNanoseconds_ be ! GetEpochFromISOParts(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]]).
        1. Let _dayBefore_ be ! CreateTemporalInstant(_epochNanoseconds_ − 8.64 × 10<sup>13</sup>).
        1. Let _dayAfter_ be ! CreateTemporalInstant(_epochNanoseconds_ + 8.64 × 10<sup>13</sup>).
        1. Let _offsetBefore_ be ? GetOffsetNanosecondsFor(_timeZone_, _dayBefore_).
        1. Let _offsetAfter_ be ? GetOffsetNanosecondsFor(_timeZone_, _dayAfter_).
        1. Let _nanoseconds_ be _offsetAfter_ − _offsetBefore_.
        1. If _disambiguation_ is *"earlier"*, then
          1. Let _earlier_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], 0, 0, 0, 0, 0, 0, 0, 0, 0, −_nanoseconds_, *"constrain"*).
          1. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _earlier_).
          1. If _possibleInstants_ is empty, throw a *RangeError* exception.
          1. Return _possibleInstants_[0].
        1. Assert: _disambiguation_ is *"compatible"* or *"later"*.
        1. Let _later_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], 0, 0, 0, 0, 0, 0, 0, 0, 0, _nanoseconds_, *"constrain"*).
        1. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _later_).
        1. Set _n_ to _possibleInstants_'s length.
        1. If _n_ = 0, throw a *RangeError* exception.
        1. Return _possibleInstants_[_n_ − 1].
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal-getpossibleinstantsfor" aoid="GetPossibleInstantsFor">
      <h1>GetPossibleInstantsFor ( _timeZone_, _dateTime_ )</h1>
      <emu-alg>
        1. Let _possibleInstants_ be ? Invoke(_timeZone_, *"getPossibleInstantsFor"*, « _dateTime_ »).
        1. Let _iteratorRecord_ be ? GetIterator(_possibleInstants_, ~sync~).
        1. Let _list_ be a new empty List.
        1. Let _next_ be *true*.
        1. Repeat, while _next_ is not *false*,
          1. Set _next_ to ? IteratorStep(_iteratorRecord_).
          1. If _next_ is not *false*, then
            1. Let _nextValue_ be ? IteratorValue(_next_).
            1. If Type(_nextValue_) is not Object or _nextValue_ does not have an [[InitializedTemporalInstant]] internal slot, then
              1. Let _completion_ be ThrowCompletion(a newly created *TypeError* object).
              1. Return ? IteratorClose(_iteratorRecord_, _completion_).
            1. Append _nextValue_ to the end of the List _list_.
        1. Return _list_.
      </emu-alg>
    </emu-clause>

    <emu-clause id="sec-temporal-timezoneequals" aoid="TimeZoneEquals">
      <h1>TimeZoneEquals ( _one_, _two_ )</h1>
      <p>
        The abstract operation TimeZoneEquals takes two arguments _one_ and _two_, which must be Objects.
        It returns *true* if its arguments represent the same time zone.
        It performs the following steps:
      </p>
      <emu-alg>
        1. If _one_ and _two_ are the same Object value, return *true*.
        1. Let _timeZoneOne_ be ? ToString(_one_).
        1. Let _timeZoneTwo_ be ? ToString(_two_).
        1. If _timeZoneOne_ is _timeZoneTwo_, return *true*.
        1. Return *false*.
      </emu-alg>
    </emu-clause>
  </emu-clause>
</emu-clause>
